package orbito;

import java.awt.Graphics2D;
import java.awt.event.KeyListener;
import java.awt.event.MouseListener;
import java.util.Collection;
import java.util.List;

import orbito.graphics.ViewFocus;
import orbito.scene.SceneGraph;

public interface GameController extends KeyListener, MouseListener {
	/**
	 * Seeds the game. When called, the game randomizer should start using this seed.
	 * 
	 * @param seed The new seed value for the randomizer.
	 */
	void seed(long seed);
	
	/**
	 * Initializes the game. When called, should initialize all the game states, and set 
	 * the main scene that will receive rendering requests and user input.
	 * 
	 * The game may be re-initialized, in which case the game should revert to its initial state.
	 */
	void init();
	
	/**
	 * Starts the game. When called, indicates that the UI has been loaded, and that the 
	 * game will now start receive rendering requests and user input. Thus, the game may 
	 * start its own states, scenes, simulator, etc, if required.
	 */
	void start();
	
	/**
	 * Pauses the game. When called, should make sure no time passes in the game.
	 */
	void pause();
	
	/**
	 * Unpauses the game. When called, should make sure to unpause the game, if paused.
	 */
	void unpause();
	
	/**
	 * Performs a time step. When called, should advance the scene of the game from time t to time t+dt.
	 * 
	 * @param t  The time before the time step, in seconds.
	 * @param dt The time that passes during the time step, in seconds.
	 */
	void step(double t, double dt);
	
	/**
	 * Renders the game. When called, should render the current game onto the given graphics context.
	 * 
	 * @param g The graphics context in which to render.
	 */
	void render(Graphics2D g);
	
	/**
	 * Handles time-dependent user input.
	 * 
	 * For example, to smoothly move the camera through the game world, the change in camera position 
	 * needs to be a function of dt, so that it may appear to move at a constant rate.
	 * 
	 * @param dt The time passed since the last time input was handled, in seconds.
	 */
	void handleInput(double dt);
	
	/**
	 * Updates the game viewport. When called, indicates a change in the size of the frame 
	 * of the game client.
	 * 
	 * @param width  The width of the viewport, in number of pixels.
	 * @param height The height of the viewport, in number of pixels.
	 */
	void updateViewport(int width, int height);
	
	/**
	 * Gets all available scenes in the game.
	 * 
	 * @return The collection of scenes currently available in the game.
	 */
	Collection<SceneGraph> getScenes();
	
	/**
	 * Gets the current scene of the game.
	 * 
	 * @return The current scene.
	 */
	SceneGraph getCurrentScene();
	
	/**
	 * Loads the given scene into the game. When called, the game controller should 
	 * gracefully suspend the current scene, if any, and load the new scene.
	 * 
	 * @param scene The scene to be loaded.
	 */
	void loadScene(SceneGraph scene);
	
	/**
	 * Resets the current scene. When called, should reset the game's current scene and simulator.
	 */
	void resetCurrentScene();
	
	/**
	 * Clears the current scene. When called, the game controller should 
	 * gracefully suspend the current scene, if any, and load no scenes.
	 */
	void clearCurrentScene();
	
	/**
	 * Gets the list of all available view focus items currently in the game.
	 * 
	 * @return The list of view focus items.
	 */
	List<ViewFocus> getViewFocusItems();
	
	/**
	 * Gets the current view focus of the game. 
	 * 
	 * @return The current view focus.
	 */
	ViewFocus getCurrentViewFocus();
	
	/**
	 * Sets the current view focus of the game.
	 * 
	 * @param focus The new view focus.
	 */
	void setCurrentViewFocus(ViewFocus focus);
	
	/**
	 * Clears the current view focus of the game, such that the game has no current focus.
	 */
	void clearCurrentViewFocus();
	
	/**
	 * If the game is paused, should return true, false otherwise.
	 * 
	 * @return true if paused, false otherwise.
	 */
	boolean isPaused();
	
	/**
	 * If the game is locking down-ward adjustment of the time step, returns true, false otherwise.
	 * 
	 * @return true if dt is down-locked, false otherwise.
	 */
	boolean isDtDownLock();
	
	/**
	 * Sets the dt down-lock.
	 * 
	 * @param b
	 */
	void setDtDownLock(boolean b);
	
	/**
	 * If the game is locking up-ward adjustment of the time step, returns true, false otherwise.
	 * 
	 * @return true if dt is up-locked, false otherwise.
	 */
	boolean isDtUpLock();
	
	/**
	 * Sets the dt up-lock.
	 * 
	 * @param b
	 */
	void setDtUpLock(boolean b);
	
	/**
	 * Decreases the game world time compression by one unit.
	 */
	void decreaseTimeCompression();
	
	/**
	 * Increases the game world time compression by one unit.
	 */
	void increaseTimeCompression();
	
	/**
	 * Invokes an update of the game UI's menu.
	 */
	void invokeUpdateMenuUi();
	
	/**
	 * Invokes an update of the game UI's scenes selection.
	 */
	void invokeUpdateScenesUi();
	
	/**
	 * Invokes an update of the game UI's focus item selection. 
	 */
	void invokeUpdateViewFocusUi();
}
